home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
network
/
ka9q
/
nhclb120.zoo
/
domain.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-20
|
24KB
|
1,122 lines
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#if defined(UNIX) || defined(GNUC)
#include <string.h>
#endif
#include "global.h"
#include "mbuf.h"
#include "netuser.h"
#include "timer.h"
#include "udp.h"
#include "cmdparse.h"
#include "domain.h"
#ifndef _STRING_H
char *strchr(), strrchr(), *strdup();
#endif
void drx(),drx_init();
extern int errno;
extern int32 Ip_addr;
struct rr *Rrlist[NRLIST];
struct dserver *Dlist; /* List of potential servers */
struct dserver *Dserver; /* Current one being used */
char *Dsuffix; /* Default suffix for names without periods */
struct socket Dsocket; /* Socket to use for domain queries */
int Dsignal;
int Drx; /* Drx started? */
int Ddebug = 0;
char *Dtypes[] = {
"",
"A",
"NS",
"MD",
"MF",
"CNAME",
"SOA",
"MB",
"MG",
"MR",
"NULL",
"WKS",
"PTR",
"HINFO",
"MINFO",
"MX",
"TXT"
};
int Ndtypes = 17;
static char delim[] = " \t\r\n";
static struct {
char *name;
int32 address;
} cache;
struct cmds Dcmds[] = {
"addserver", doadds, 0, 0, NULLCHAR,
"dropserver", dodropds, 0, 0, NULLCHAR,
"suffix", dosuffix, 0, 0, NULLCHAR,
"trace", dodtrace, 0, 0, NULLCHAR,
NULLCHAR, NULLFP, 0, 0, "domain subcommands: addserver dropserver suffix trace",
};
int
dodtrace(argc,argv)
int argc;
char *argv[];
{
if(argc < 2){
printf("Domain trace: %s\n",Ddebug ? "On" : "Off");
} else {
if(strcmp(argv[1],"on") == 0)
Ddebug = 1;
else
Ddebug = 0;
}
return 0;
}
int
dodomain(argc,argv,envp)
int argc;
char *argv[];
char *envp;
{
return subcmd(Dcmds,argc,argv,envp);
}
int
dosuffix(argc,argv)
int argc;
char *argv[];
{
if(argc < 2){
if(Dsuffix != NULLCHAR)
printf("%s\n",Dsuffix);
return 0;
}
free(Dsuffix);
Dsuffix = strdup(argv[1]);
return 0;
}
int
doadds(argc,argv)
int argc;
char *argv[];
{
struct dserver *dp;
int32 address;
if((address = resolve(argv[1])) == 0){
printf("Resolver %s unknown\n",argv[1]);
return 1;
}
dp = (struct dserver *)calloc(1,sizeof(struct dserver));
dp->address = address;
dp->srtt = 5L;
dp->timeout = dp->srtt * 2;
dp->mdev = 0;
dp->next = Dlist;
if(dp->next != NULLDOM)
dp->next->prev = dp;
Dlist = dp;
Dserver = dp; /* Make this the first one we try next */
if(Drx == 0){
/* Start domain task upon first addserver */
drx_init();
Drx = 1;
}
return 0;
}
int
dodropds(argc,argv)
int argc;
char *argv[];
{
struct dserver *dp;
int32 addr;
addr = resolve(argv[1]);
for(dp = Dlist;dp != NULLDOM;dp = dp->next)
if(addr == dp->address)
break;
if(dp == NULLDOM){
printf("Not found\n");
return 1;
}
if(dp->prev != NULLDOM)
dp->prev->next = dp->next;
else
Dlist = dp->next;
if(dp->next != NULLDOM)
dp->next->prev = dp->prev;
if(Dserver == dp)
Dserver = Dlist;
free((char *)dp);
return 0;
}
/* Search local domain file for resource record of specified type.
* If a record is found, the domain file pointer is left just after it. If
* not, the file is rewound.
*/
static struct rr *
dfind(dbase,name,type)
FILE *dbase;
char *name;
int type;
{
struct rr *rrp;
int nlen;
/* Search file */
while((rrp = getrr(dbase)) != NULLRR){
if((nlen = strlen(name)) == strlen(rrp->name)
&& strncasecmp(name,rrp->name,nlen) == 0
&& rrp->class == CLASS_IN
&& rrp->type == type)
break;
free_rr(rrp);
/* pwait(NULL); /* Give up CPU for a while, this is slow */
}
if(rrp == NULLRR)
rewind(dbase);
return rrp;
}
static struct rr *
getrr(fp)
FILE *fp;
{
char *line,*strtok();
struct rr *rrp;
char *name,*ttl,*class,*type,*data;
int i;
line = malloc(256);
/* Search file */
while(fgets(line,256,fp),!feof(fp)){
if(line[0] != '#')
break;
}
if(feof(fp) || (rrp = (struct rr *)calloc(1,sizeof(struct rr))) == NULLRR){
free(line);
return NULLRR;
}
name = strtok(line,delim);
ttl = strtok(NULLCHAR,delim);
class = strtok(NULLCHAR,delim);
type = strtok(NULLCHAR,delim);
data = strtok(NULLCHAR,delim);
rrp->name = strdup(name);
if(!isdigit(ttl[0])){
/* Optional ttl field is missing; slide the other fields over */
data = type;
type = class;
class = ttl;
ttl = NULLCHAR;
} else {
rrp->ttl = atol(ttl);
}
for(i=0;i<NRLIST;i++){
if(strcmp(type,Dtypes[i]) == 0){
rrp->type = i;
break;
}
}
if(strcmp(class,"IN") == 0)
rrp->class = CLASS_IN;
if(data == NULLCHAR){
/* Empty record, just return */
free(line);
return rrp;
}
switch(rrp->type){
case TYPE_CNAME:
case TYPE_MB:
case TYPE_MG:
case TYPE_MR:
case TYPE_NS:
case TYPE_PTR:
case TYPE_TXT:
rrp->rdlength = strlen(data);
rrp->rdata.name = strdup(data);
break;
case TYPE_A:
rrp->rdlength = 4;
rrp->rdata.addr = aton(data);
break;
case TYPE_HINFO:
rrp->rdlength = strlen(data);
rrp->rdata.hinfo.cpu = strdup(data);
if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
rrp->rdlength += strlen(data);
rrp->rdata.hinfo.os = strdup(data);
}
break;
case TYPE_MX:
rrp->rdata.mx.pref = atoi(data);
rrp->rdlength = 2;
/* Get domain name of exchanger */
if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
rrp->rdlength += strlen(data);
rrp->rdata.mx.exch = strdup(data);
}
break;
case TYPE_SOA:
/* Get domain name of master name server */
rrp->rdlength = strlen(data);
rrp->rdata.soa.mname = strdup(data);
/* Get domain name of irresponsible person */
if((data = strtok(NULLCHAR,delim)) != NULLCHAR){
rrp->rdata.soa.rname = strdup(data);
rrp->rdlength += strlen(data);
}
data = strtok(NULLCHAR,delim);
rrp->rdata.soa.serial = atol(data);
data = strtok(NULLCHAR,delim);
rrp->rdata.soa.refresh = atol(data);
data = strtok(NULLCHAR,delim);
rrp->rdata.soa.retry = atol(data);
data = strtok(NULLCHAR,delim);
rrp->rdata.soa.expire = atol(data);
data = strtok(NULLCHAR,delim);
rrp->rdata.soa.minimum = atol(data);
rrp->rdlength += 20;
break;
}
free(line);
return rrp;
}
/* Search for address record in local database, looking first for PTR
* and CNAME records. Return values:
* 0xffffffff Not found (domain name may exist, but we don't know yet)
* 0 Domain name definitely doesn't exist (we have a null record)
*/
int32
dresolve(name)
char *name;
{
register struct rr *rrp;
char *pname = NULLCHAR;
char *cname = NULLCHAR;
int32 result;
FILE *dbase;
if(cache.name != NULLCHAR && strcmp(cache.name,name) == 0)
return cache.address;
if((dbase = fopen(Dfile,"r")) == NULLFILE)
return 0xffffffff;
/* This code can handle a few weird cases. It works when there's
* a PTR to a CNAME to an A record, as well as when there's a
* a CNAME to a PTR to an A. But it allows only one of each kind
* of indirection to prevent infinite loops.
*/
while((rrp = dfind(dbase,name,TYPE_A)) == NULLRR){
/* An address record didn't exist, let's see if it's an alias */
if(cname == NULLCHAR && (rrp = dfind(dbase,name,TYPE_CNAME)) != NULLRR){
if((cname = strdup(rrp->rdata.name)) == NULLCHAR)
break;
name = cname;
rewind(dbase);
free_rr(rrp);
continue; /* Try again */
}
/* Lacking that, try a pointer entry... */
if(pname == NULLCHAR && (rrp = dfind(dbase,name,TYPE_PTR)) != NULLRR){
if((pname = strdup(rrp->rdata.name)) == NULLCHAR)
break;
name = pname;
rewind(dbase);
free_rr(rrp);
continue;
}
/* Nope, nothing. Give up */
break;
}
fclose(dbase);
free(pname);
free(cname);
if(rrp == NULLRR){
result = 0xffffffff; /* No record in database */
} else {
if(rrp->rdlength == 0)
result = 0; /* Negative response record */
else
result = rrp->rdata.addr; /* Normal return */
free(cache.name);
cache.name = strdup(name);
cache.address = result;
free_rr(rrp);
}
return result;
}
static int numeric_only(char *name)
{
/* return true if name in in form nnn.nnn.nnn.nnn, where n is 0-9 */
if(name == (char *) 0 || *name =='\0' ) return(0);
while( *name ){
if(*name == '.' || isdigit(*name)) { name++; continue; }
return(0);
}
return (-1);
}
/* Main entry point for domain name -> address resolution. Returns 0 if
* name is definitely not valid.
*/
int32
resolve(name)
char *name;
{
char *buf;
int32 addr;
struct dserver *dp;
struct mbuf *bp;
int len;
struct socket server;
char *tname = NULLCHAR;
char *p